﻿using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
using System.Text;
using Sinacor.Infra.Service.Data;
using Sinacor.Infra.Service.Security.Authorization;

namespace Sinacor.Servico.Bovespa.Ordens.ResourceAccess
{
    /// <summary>
    /// ResourceAccess Class - AjusteMercadoFuturo
    /// </summary>
    public class AjusteMercadoFuturo : BaseResourceAccess
    {
        #region Construtor

        /// <summary>
        /// Construtor
        /// </summary>
        public AjusteMercadoFuturo() : base(AuthorizationContext.Current.CompanyId) { }

        #endregion

        #region Constantes de Erro

        /// <summary>
        /// Constante contendo o código da BusinessException
        /// </summary>
        private const int ERRO_AJUSTEMERCADOFUTURO_CALCULOAJUSTEPOSICAO = 109029;

        #endregion

        #region Métodos Públicos

        /// <summary>
        /// Calcula ajuste de posição de mercado futuro
        /// </summary>
        /// <param name="request">Data do Pregão</param>
        public BusinessEntity.Resultado AjustarPosicao(System.DateTime request)
        {
            StringBuilder sql = new StringBuilder();
            BusinessEntity.Resultado resultado = new Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Resultado();

            sql.Append("DECLARE rettype BOOLEAN; ");
            sql.Append("BEGIN ");
            sql.Append("rettype:= PR_AJUSTE.fOr_CalculaAjuste( :P_sDtPregao, :R_nErro, :R_sErro, :R_sArgs );");
            sql.Append("END; ");

            DbCommand dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());

            DbParameter parametrooP_sDtPregao = dbCommand.CreateParameter();
            parametrooP_sDtPregao.ParameterName = "P_sDtPregao";
            parametrooP_sDtPregao.Direction = ParameterDirection.Input;
            parametrooP_sDtPregao.DbType = DbType.String;
            parametrooP_sDtPregao.Value = request.ToString("dd/MM/yyyy");

            dbCommand.Parameters.Add(parametrooP_sDtPregao);

            DbParameter parametroR_nErro = dbCommand.CreateParameter();
            parametroR_nErro.ParameterName = "R_nErro";
            parametroR_nErro.Direction = ParameterDirection.Output;
            parametroR_nErro.DbType = DbType.Int32;
            parametroR_nErro.Value = 0;

            dbCommand.Parameters.Add(parametroR_nErro);

            DbParameter parametroR_sErro = dbCommand.CreateParameter();
            parametroR_sErro.ParameterName = "R_sErro";
            parametroR_sErro.Direction = ParameterDirection.Output;
            parametroR_sErro.DbType = DbType.String;
            parametroR_sErro.Size = 4000;
            parametroR_sErro.Value = null;

            dbCommand.Parameters.Add(parametroR_sErro);

            DbParameter parametroR_sArgs = dbCommand.CreateParameter();
            parametroR_sArgs.ParameterName = "R_sArgs";
            parametroR_sArgs.Direction = ParameterDirection.Output;
            parametroR_sArgs.DbType = DbType.String;
            parametroR_sArgs.Size = 4000;
            parametroR_sArgs.Value = null;

            dbCommand.Parameters.Add(parametroR_sArgs);

            this.DataBase.ExecuteNonQuery(dbCommand);

            // validação - Implementação Task 6417 - FGualberto.7Comm
            if (Convert.ToInt32(parametroR_nErro.Value) == 0)
            {
                resultado.Sucesso = true;
            }
            else
            {
                resultado.Sucesso = false;
                resultado.CodigoErro = Convert.ToInt32(parametroR_nErro.Value);
                resultado.Argumentos = Convert.ToString(parametroR_sArgs.Value);
            }

            return resultado;

            //if (Convert.ToInt32(parametroR_nErro.Value) != 0)
            //    //Ocorreu um erro no calculo do ajuste de posição
            //    throw new BusinessException(ERRO_AJUSTEMERCADOFUTURO_CALCULOAJUSTEPOSICAO);

        }

        /// <summary>
        /// Altera um registro de ajuste de mercado futuro
        /// </summary>
        /// <param name="request">Entidade AjusteMercadoFuturo</param>
        public void AlterarAjusteMercadoFuturo(BusinessEntity.AjusteMercadoFuturo request)
        {
            #region Comando SQL

            StringBuilder sql = new StringBuilder();

            sql.Append("UPDATE TCFCOT_ACAO ");
            sql.Append("SET COT_AJU_ANT = :ValorAjusteAnterior, COT_AJU_ATU = :ValorAjusteAtual, PERC_VAR_AJU = :Variacao ");
            sql.Append("WHERE ");
            sql.Append("DATA_PREG = :DataPregao ");
            sql.Append("AND ANO_PREG = :AnoPregao ");
            sql.Append("AND COD_NEG = :CodigoNegociacao ");
            sql.Append("AND TIPO_MERC = 'FUT'");

            DbCommand dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());

            #endregion

            #region Adição dos parâmetros

            this.DataBase.AddInParameter(dbCommand, "ValorAjusteAnterior", DbType.Decimal, request.ValorAjusteAnterior);
            this.DataBase.AddInParameter(dbCommand, "ValorAjusteAtual", DbType.Decimal, request.ValorAjusteAtual);
            this.DataBase.AddInParameter(dbCommand, "Variacao", DbType.Decimal, request.Variacao);
            this.DataBase.AddInParameter(dbCommand, "DataPregao", DbType.DateTime, request.DataPregao);
            this.DataBase.AddInParameter(dbCommand, "AnoPregao", DbType.Int32, request.AnoPregao);
            this.DataBase.AddInParameter(dbCommand, "CodigoNegociacao", DbType.String, request.CodigoNegocio);

            #endregion

            #region Execução

            this.DataBase.ExecuteNonQuery(dbCommand);

            #endregion
        }

        /// <summary>
        /// Consulta registros de ajustes de mercado futuro
        /// </summary>
        /// <param name="request">Filtro contendo o código do negócio(opcional)</param>
        /// <returns>Lista de entidades AjusteMercadoFuturo</returns>
        public List<BusinessEntity.AjusteMercadoFuturo> ConsultarAjustesMercadoFuturo(BusinessEntity.Parameter.FiltroAjusteMercadoFuturo request)
        {
            #region Comando SQL

            StringBuilder sql = new StringBuilder();

            sql.Append("SELECT ");
            sql.Append("DATA_PREG, ANO_PREG, COD_NEG, ");
            sql.Append("TIPO_MERC, PREC_EXER, FAT_COT, ");
            sql.Append("COT_AJU_ANT, COT_AJU_ATU, PERC_VAR_AJU ");
            sql.Append("FROM TCFCOT_ACAO ");
            sql.Append("WHERE COD_NEG IS NOT NULL ");
            sql.Append("AND TIPO_MERC = 'FUT' ");
            sql.Append("AND DATA_PREG = :DataPregao ");

            //Filtro Opcional - Código do Negócio
            if (request.CodigoNegociacao != null && request.CodigoNegociacao != string.Empty)
                sql.Append("AND COD_NEG = :CodigoNegociacao ");

            sql.Append("ORDER BY DATA_PREG, COD_NEG");

            DbCommand dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());

            #endregion

            #region Adição dos parâmetros

            this.DataBase.AddInParameter(dbCommand, "DataPregao", DbType.DateTime, request.DataPregao);

            if (request.CodigoNegociacao != null && request.CodigoNegociacao != string.Empty)
                this.DataBase.AddInParameter(dbCommand, "CodigoNegociacao", DbType.String, request.CodigoNegociacao);

            #endregion

            #region Execução

            List<BusinessEntity.AjusteMercadoFuturo> response = new List<Sinacor.Servico.Bovespa.Ordens.BusinessEntity.AjusteMercadoFuturo>();
            BusinessEntity.AjusteMercadoFuturo responseItem;

            using (IDataReader reader = this.DataBase.ExecuteReader(dbCommand))
            {
                while (reader.Read())
                {
                    responseItem = new Sinacor.Servico.Bovespa.Ordens.BusinessEntity.AjusteMercadoFuturo();

                    responseItem.DataPregao = reader.GetValue<DateTime>("DATA_PREG");
                    responseItem.AnoPregao = reader.GetValue<Int32>("ANO_PREG");
                    responseItem.CodigoNegocio = reader.GetValue<String>("COD_NEG");
                    responseItem.Tipo = BusinessEntity.Enum.TipoMercado.Futuro;
                    responseItem.PrecoExercicio = reader.GetValue<Decimal>("PREC_EXER");
                    responseItem.Fator = reader.GetValue<Decimal>("FAT_COT");
                    responseItem.ValorAjusteAnterior = reader.GetValue<Decimal>("COT_AJU_ANT");
                    responseItem.ValorAjusteAtual = reader.GetValue<Decimal>("COT_AJU_ATU");
                    responseItem.Variacao = reader.GetValue<Decimal>("PERC_VAR_AJU");

                    response.Add(responseItem);
                }
            }

            return response;

            #endregion
        }

        /// <summary>
        /// Exclui um registro de ajuste de mercado futuro
        /// </summary>
        /// <param name="request">Filtro contendo o código do negócio, data do pregão e o ano do pregão</param>
        public void ExcluirAjusteMercadoFuturo(BusinessEntity.Parameter.FiltroAjusteMercadoFuturo request)
        {
            #region Comando SQL

            StringBuilder sql = new StringBuilder();

            sql.Append("DELETE FROM TCFCOT_ACAO ");
            sql.Append("WHERE COD_NEG = :CodigoNegociacao ");
            sql.Append("AND DATA_PREG = :DataPregao ");
            sql.Append("AND ANO_PREG = :AnoPregao ");
            sql.Append("AND TIPO_MERC = 'FUT'");

            DbCommand dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());

            #endregion

            #region Adição dos parâmetros

            this.DataBase.AddInParameter(dbCommand, "CodigoNegociacao", DbType.String, request.CodigoNegociacao);
            this.DataBase.AddInParameter(dbCommand, "DataPregao", DbType.DateTime, request.DataPregao);
            this.DataBase.AddInParameter(dbCommand, "AnoPregao", DbType.Int32, request.DataPregao.Value.Year);

            #endregion

            #region Execução

            this.DataBase.ExecuteNonQuery(dbCommand);

            #endregion
        }

        /// <summary>
        /// Inclui um registro de ajuste de mercado futuro
        /// </summary>
        /// <param name="request">Entidade AjusteMercadoFuturo</param>
        public void IncluirAjusteMercadoFuturo(BusinessEntity.AjusteMercadoFuturo request)
        {
            #region Comando SQL

            StringBuilder sql = new StringBuilder();

            sql.Append("INSERT INTO TCFCOT_ACAO ");
            sql.Append("( DATA_PREG, ANO_PREG, COD_NEG, TIPO_MERC, PREC_EXER, COT_MED, FAT_COT, COT_AJU_ANT, COT_AJU_ATU, PERC_VAR_AJU ) ");
            sql.Append("VALUES ");
            sql.Append("( :DataPregao, :AnoPregao, :CodigoNegociacao,'FUT', :PrecoExercicio, NULL, :Fator, :ValorAjusteAnterior, :ValorAjusteAtual, :Variacao )");

            DbCommand dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());

            #endregion

            #region Adição dos parâmetros

            this.DataBase.AddInParameter(dbCommand, "DataPregao", DbType.DateTime, request.DataPregao);
            this.DataBase.AddInParameter(dbCommand, "AnoPregao", DbType.Int32, request.AnoPregao);
            this.DataBase.AddInParameter(dbCommand, "CodigoNegociacao", DbType.String, request.CodigoNegocio);
            this.DataBase.AddInParameter(dbCommand, "PrecoExercicio", DbType.Decimal, request.PrecoExercicio);
            this.DataBase.AddInParameter(dbCommand, "Fator", DbType.Decimal, request.Fator);
            this.DataBase.AddInParameter(dbCommand, "ValorAjusteAnterior", DbType.Decimal, request.ValorAjusteAnterior);
            this.DataBase.AddInParameter(dbCommand, "ValorAjusteAtual", DbType.Decimal, request.ValorAjusteAtual);
            this.DataBase.AddInParameter(dbCommand, "Variacao", DbType.Decimal, request.Variacao);

            #endregion

            #region Execução

            this.DataBase.ExecuteNonQuery(dbCommand);

            #endregion
        }

        #endregion
    }
}
